#include "Structures.fxh"
#include "Lighting.fxh"

cbuffer PerFrame {
	uniform float4x4 VP;
	uniform float3 EyePos;
};

//CBuffer for lighting values
cbuffer Lighting {
	uniform float3 GlobalAmbient : GLOBALAMBIENT = { 0.0f, 0.0f, 0.0f };
	uniform Light Lights[4] : LIGHTLIST;
	uniform int NumLights : LIGHTCOUNT = 0;
};

//CBuffer for material properties
cbuffer PerMaterial {
	uniform float3 MatDiffuse = { 1.0f, 1.0f, 1.0f};
	uniform float3 MatAmbient = { 0.2f, 0.2f, 0.2f};
	uniform float3 MatEmissive = { 0.0f, 0.0f, 0.0f};
	uniform float3 MatSpecular = { 0.0f, 0.0f, 0.0f};
	uniform float MatShininess = 16.0f;
	uniform float Alpha = 1.0f;
};


uniform Texture3D Texture;
uniform Texture1D Ramp;
uniform Texture2D DiffuseMap;
uniform SamplerState DiffuseMapSampler {
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

struct VSInputInstanced {
	float3 Position : POSITION;
	float3 Normal : NORMAL;
	float4 VertColor : COLOR;
	float2 TexCoord : TEXCOORD0;
	float4x4 World : TEXCOORD1;
};


//
// **** InstancedVertColorTexture ****
//

VSOutputNmVcTx VS_InstancedVcTx(VSInputInstanced input) {
	VSOutputNmVcTx output;
	float4 pos = float4(input.Position, 1.0);
	float4x4 world = transpose(input.World);
	float4x4 wvp = mul(world, VP);
	output.PositionPS =  mul(pos, wvp);
	output.PositionWS = mul(pos, world).xyz;
	output.Normal = normalize(mul(float4(input.Normal, 0.0), world).xyz);
	output.TexCoord = input.TexCoord;
	output.VertColor = input.VertColor;
	return output;
}

float4 PS_BasicVcTx(VSOutputVcTx input) : SV_TARGET {
	float4 albedo = DiffuseMap.Sample(DiffuseMapSampler, input.TexCoord);
	return albedo * float4(MatDiffuse, 1.0f) * input.VertColor;
}

float4 PS_LitBasicNmVcTx(VSOutputNmVcTx input) : SV_TARGET {
	//Individual light contribs from each light
	float3 lightContribs = float3(0,0,0);

	//Get the diffuse map color
	float4 albedo = DiffuseMap.Sample(DiffuseMapSampler, input.TexCoord);

	Material mat;
	mat.Ambient = MatAmbient;
	mat.Diffuse = MatDiffuse;
	mat.Specular = MatSpecular;
	mat.Shininess = MatShininess;

	//Calculate the V vector for specular highlights
	float3 V = normalize(EyePos - input.PositionWS);

	float3 normal = input.Normal;
	float3 pos = input.PositionWS;

	for(int i = 0; i < NumLights; i++) {
		Light l = Lights[i];
		LightResult result = ComputeSingleLight(l, pos, normal, V, mat);
		float3 diffuse = (result.Diffuse + result.Ambient) * input.VertColor.rgb * albedo.rgb;
		float3 specular = result.Specular;
		lightContribs += ComputeAttenuation(pos, l) * SpotEffect(pos, l) * (diffuse + specular);
	}

	float3 color = (MatAmbient * GlobalAmbient) + MatEmissive + lightContribs;

	return float4(color, Alpha * input.VertColor.a * albedo.a);
}

technique10 Instanced {
	pass Pass0 {
		SetGeometryShader(0);
		SetVertexShader(CompileShader(vs_4_0, VS_InstancedVcTx()));
		SetPixelShader(CompileShader(ps_4_0, PS_LitBasicNmVcTx()));
	}
}